#include "Global.h"



extern byte CAM_FRAMEBUFFER_C[1024*1024*4];
extern byte CAM_FRAMEBUFFER_P[1024*1024*4];
ushort LCD_BUFFER_CAM[LCD_CAM_YSIZE][LCD_CAM_XSIZE]  __attribute__((aligned (16)));;
byte CamProcBuf[LCD_CAM_YSIZE*LCD_CAM_XSIZE*4]  __attribute__((aligned (16)));;

//*****************************************************************************

volatile uint camTestMode;
volatile uint camCodecCaptureCount;
volatile uint camPviewCaptureCount;
volatile uint camCodecStatus;
volatile uint camPviewStatus;
volatile uint amount;
volatile uint camOutputCount;
volatile uint camOutputReady;


#define CHIP_DELAY 0xFF
#define OV9620_SCCB_ID 0x60
#define OV7620_PRODUCT_ID 		0x7FA2

#define OV9620REGLEN 123


//#define BUSHI_DEF 0
OVVisionREG ov9650_reg[] = 
{
//{0x12, 0x80},	// Camera Soft reset. Self cleared after reset.
//change 0x11[0x81->0x80], 0x15[0x02->0x10], hzh
{0x11,0x80},{0x6a,0x3e},{0x3b,0x09},{0x13,0xe0},{0x01,0x80},{0x02,0x80},{0x00,0x00},{0x10,0x00},{0x13,0xe5},{0x39,0x43},
{0x38,0x12},{0x37,0x00},{0x35,0x91},{0x0e,0xa0},{0x1e,0x04},{0xA8,0x80},{0x12,0x40},{0x04,0x00},{0x0c,0x04},{0x0d,0x80},
{0x18,0xc6},{0x17,0x26},{0x32,0xad},{0x03,0x00},{0x1a,0x3d},{0x19,0x01},{0x3f,0xa6},{0x14,0x2e},{0x15,0x10},{0x41,0x02},
{0x42,0x08},{0x1b,0x00},{0x16,0x06},{0x33,0xe2},{0x34,0xbf},{0x96,0x04},{0x3a,0x00},{0x8e,0x00},{0x3c,0x77},{0x8B,0x06},
{0x94,0x88},{0x95,0x88},{0x40,0xc1},{0x29,0x3f},{0x0f,0x42},{0x3d,0x92},{0x69,0x40},{0x5C,0xb9},{0x5D,0x96},{0x5E,0x10},
{0x59,0xc0},{0x5A,0xaf},{0x5B,0x55},{0x43,0xf0},{0x44,0x10},{0x45,0x68},{0x46,0x96},{0x47,0x60},{0x48,0x80},{0x5F,0xe0},
{0x60,0x8c},{0x61,0x20},{0xa5,0xd9},{0xa4,0x74},{0x8d,0x02},{0x13,0xe7},{0x4f,0x3a},{0x50,0x3d},{0x51,0x03},{0x52,0x12},
{0x53,0x26},{0x54,0x38},{0x55,0x40},{0x56,0x40},{0x57,0x40},{0x58,0x0d},{0x8C,0x23},{0x3E,0x02},{0xa9,0xb8},{0xaa,0x92},
{0xab,0x0a},{0x8f,0xdf},{0x90,0x00},{0x91,0x00},{0x9f,0x00},{0xa0,0x00},{0x3A,0x01},{0x24,0x70},{0x25,0x64},{0x26,0xc3},
{0x2a,0x00},{0x2b,0x00},{0x6c,0x40},{0x6d,0x30},{0x6e,0x4b},{0x6f,0x60},{0x70,0x70},{0x71,0x70},{0x72,0x70},{0x73,0x70},
{0x74,0x60},{0x75,0x60},{0x76,0x50},{0x77,0x48},{0x78,0x3a},{0x79,0x2e},{0x7a,0x28},{0x7b,0x22},{0x7c,0x04},{0x7d,0x07},
{0x7e,0x10},{0x7f,0x28},{0x80,0x36},{0x81,0x44},{0x82,0x52},{0x83,0x60},{0x84,0x6c},{0x85,0x78},{0x86,0x8c},{0x87,0x9e},
{0x88,0xbb},{0x89,0xd2},{0x8a,0xe6},
};


void CamPreviewIntUnmask(void)
{
    rINTSUBMSK &= ~(BIT_SUB_CAM_P);//INT CAMERA Port A ENABLE 
    rINTMSK &= ~(BIT_CAM);
}

void CamCodecIntUnmask(void)
{
    rINTSUBMSK &= ~(BIT_SUB_CAM_C);//INT CAMERA Port B ENABLE 
    rINTMSK &= ~(BIT_CAM);
}

void CamPreviewIntMask(void)
{
    rINTSUBMSK |= BIT_SUB_CAM_P;//INT CAMERA Port A ENABLE 
    rINTMSK |= (BIT_CAM);
}

void CamCodecIntMask(void)
{
    rINTSUBMSK |= BIT_SUB_CAM_C;//INT CAMERA Port B ENABLE 
    rINTMSK |= (BIT_CAM);
}


void CamCamModuleReset(void)
{
	rCIGCTRL |= (1<<30);	  //external camera reset high
	Delay(30);
	rCIGCTRL &= ~(1<<30);	//external camera reset low
}

void CamCaptureStart(uint mode)
{ 
    
	if(mode&CAM_CODEC_SCALER_CAPTURE_ENABLE_BIT) {
		camCodecStatus=CAM_STARTED;
		rCICOSCCTRL|=CAM_CODEC_SACLER_START_BIT;
	}
	
	if(mode&CAM_PVIEW_SCALER_CAPTURE_ENABLE_BIT) {
		camPviewStatus=CAM_STARTED;
		rCIPRSCCTRL|=CAM_PVIEW_SACLER_START_BIT;
	}
	
	rCIIMGCPT|=CAM_CAMIF_GLOBAL_CAPTURE_ENABLE_BIT|mode;
}

void CamCaptureStop(void)
{
	camCodecStatus=CAM_STOP_ISSUED;
	camPviewStatus=CAM_STOP_ISSUED;
}


void _CamCodecStopHw(void)
{
	rCICOSCCTRL &= ~CAM_CODEC_SACLER_START_BIT; //stop codec scaler.
	rCIIMGCPT &= ~CAM_CODEC_SCALER_CAPTURE_ENABLE_BIT; //stop capturing for codec scaler.
	if(!(rCIIMGCPT & CAM_PVIEW_SCALER_CAPTURE_ENABLE_BIT))
		rCIIMGCPT &= ~CAM_CAMIF_GLOBAL_CAPTURE_ENABLE_BIT; //stop capturing for preview scaler if needed.
	rCICOCTRL |= (1<<2); //Enable last IRQ at the end of frame capture.
		       //NOTE:LastIrqEn bit should be set after clearing CAPTURE_ENABLE_BIT & SCALER_START_BIT
}

void _CamPviewStopHw(void)
{
	rCIPRSCCTRL &= ~CAM_PVIEW_SACLER_START_BIT; //stop preview scaler.
	rCIIMGCPT &= ~CAM_PVIEW_SCALER_CAPTURE_ENABLE_BIT; //stop capturing for preview scaler.
	if(!(rCIIMGCPT&CAM_CODEC_SCALER_CAPTURE_ENABLE_BIT))
		rCIIMGCPT &= ~CAM_CAMIF_GLOBAL_CAPTURE_ENABLE_BIT; //stop capturing for codec scaler if needed.
	rCIPRCTRL |= (1<<2); //Enable last IRQ at the end of frame capture.
       	//NOTE:LastIrqEn bit should be set after clearing CAPTURE_ENABLE_BIT & SCALER_START_BIT
}


void CamIsr(void)
{
	uint completedFrameIndex;
	OSIntEnter();
	
	if((rSUBSRCPND&BIT_SUB_CAM_C)||(rSUBSRCPND&BIT_SUB_CAM_P))
	{
		rGPFDAT^=1<<5;	//capbily
		if(rSUBSRCPND&BIT_SUB_CAM_C)
		{
			CamCodecIntMask();
			//rSUBSRCPND |= BIT_SUB_CAM_C;
			ClearSubPending(BIT_SUB_CAM_C);
			camOutputReady=1;
		}

		if(rSUBSRCPND&BIT_SUB_CAM_P)
		{
			CamPreviewIntMask();
			//rSUBSRCPND |= BIT_SUB_CAM_P;
			ClearSubPending(BIT_SUB_CAM_P);
		}

		ClearPending(BIT_CAM);
		switch(camCodecStatus) 
		{
			case CAM_STOP_ISSUED:
				if(camTestMode&CAM_TEST_MODE_CODEC)	
				{
					_CamCodecStopHw();
					camCodecStatus=CAM_LAST_CAPTURING;
				}

				if(camTestMode&CAM_TEST_MODE_PVIEW) 
				{
					_CamPviewStopHw();
					camPviewStatus=CAM_LAST_CAPTURING;	 
				}
				DbgOut("pr=%x\n", rCIPRCTRL);

				break;
			case CAM_LAST_CAPTURING:
				if(camTestMode&CAM_TEST_MODE_CODEC)	
				{
					camCodecStatus=CAM_STOPPED;
					CamCodecIntMask();			
				}
				
				if(camTestMode&CAM_TEST_MODE_PVIEW) 
				{
					camPviewStatus=CAM_STOPPED;
					CamPreviewIntMask();
				}
				return;
				
			case CAM_STARTED:
				if(camTestMode&CAM_TEST_MODE_CODEC)	
				{
					if(camCodecCaptureCount>0) 
					completedFrameIndex=(((rCICOSTATUS>>26)&0x3)+4-2)%4;   
				}

				if(camTestMode&CAM_TEST_MODE_PVIEW) 
				{
					if(camPviewCaptureCount >0) 
					completedFrameIndex=(((rCIPRSTATUS>>26)&0x3)+4-2)%4;
				}
				break;
			case CAM_CODEC_SCALER_BYPASS_STATE:
				break;
			default:
				break;
		}
		if(camTestMode&CAM_TEST_MODE_CODEC)	
		{
			CamCodecIntUnmask();
			camCodecCaptureCount++;	 
		}

		if(camTestMode&CAM_TEST_MODE_PVIEW) 
		{
			CamPreviewIntUnmask();
			camPviewCaptureCount++;		
		}
	}

#if 0
	if (rSUBSRCPND&BIT_SUB_CAM_C)
	{
		//DbgOut("[C]");
		rGPFDAT ^= 1<<5;	//capbily
		CamCodecIntMask();
		rSUBSRCPND |= BIT_SUB_CAM_C;
		ClearPending(BIT_CAM);
		switch(camCodecStatus) {
			case CAM_STOP_ISSUED:
				_CamCodecStopHw();
				camCodecStatus=CAM_LAST_CAPTURING;
				DbgOut("cr=%x\n", rCICOCTRL);
				//DbgOut("cS1\n");
				break;
			case CAM_LAST_CAPTURING:
				camCodecStatus=CAM_STOPPED;
				CamCodecIntMask();			
				//DbgOut("cS2\n");
				return;
			case CAM_STARTED:
//				_CamCodecStopHw();
				if(camTestMode&CAM_TEST_MODE_CODEC)	{
					if(camCodecCaptureCount>0) 
						completedFrameIndex=(((rCICOSTATUS>>26)&0x3)+4-2)%4;   
					//DbgOut("FrameIndex:%d\n",completedFrameIndex);
				}
				else {
					//DbgOut("Just Capturing without display");
				}
				break;
			case CAM_CODEC_SCALER_BYPASS_STATE:
				//DbgOut("cBP\n");
				break;
			default:
				break;
		}
			
		CamCodecIntUnmask();
	    camCodecCaptureCount++;	 
	}
	else
	{
		//DbgOut("[P]");
		rGPFDAT ^= 1<<4;	//capbily
		CamPreviewIntMask();
		rSUBSRCPND |= BIT_SUB_CAM_P;
		ClearPending(BIT_CAM) ;
		switch(camPviewStatus) {
			case CAM_STOP_ISSUED:
				_CamPviewStopHw();
				camPviewStatus=CAM_LAST_CAPTURING;	 
				DbgOut("pr=%x\n", rCIPRCTRL);
				//DbgOut("pS1\n");
				break;
			case CAM_LAST_CAPTURING:
				camPviewStatus=CAM_STOPPED;
				CamPreviewIntMask();
				//DbgOut("pS2\n"); 	
				return;
			case CAM_STARTED:
				if(camTestMode&CAM_TEST_MODE_PVIEW) {
					if(camPviewCaptureCount >0) 
						completedFrameIndex=(((rCIPRSTATUS>>26)&0x3)+4-2)%4;
					//DbgOut("FrameIndex:%d\n",completedFrameIndex);
				}
				else {
					//DbgOut("Preview Image Captured\n");
				} 		
			default:
				break;			
		} 	
		
		CamPreviewIntUnmask();
		camPviewCaptureCount++;
	}
#endif	

	OSIntExit();	

}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //CalculateBurstSize - Calculate the busrt lengths
//  Description:	
// - dstHSize: the number of the byte of H Size.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CalculateBurstSize(uint hSize,uint *mainBurstSize,uint *remainedBurstSize)
{
	uint tmp;	
	tmp=(hSize/4)%16;
	switch(tmp) 
	{
		case 0:
			*mainBurstSize=16;
			*remainedBurstSize=16;
			break;
		case 4:
			*mainBurstSize=16;
			*remainedBurstSize=4;
			break;
		case 8:
			*mainBurstSize=16;
			*remainedBurstSize=8;
			break;
		default: 
			tmp=(hSize/4)%8;
			switch(tmp) 
			{
				case 0:
					*mainBurstSize=8;
					*remainedBurstSize=8;
					break;
				case 4:
					*mainBurstSize=8;
					*remainedBurstSize=4;
				default:
					*mainBurstSize=4;
					tmp=(hSize/4)%4;
					*remainedBurstSize= (tmp) ? tmp: 4;
					break;
			}
			break;
	}		    	    		
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CalculatePrescalerRatioShift - none
// 
// Description:	
// - none
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CalculatePrescalerRatioShift(uint SrcSize, uint DstSize, uint *ratio,uint *shift)
{
	if(SrcSize>=64*DstSize) 
	{
		assert(0);
		DbgOut("ERROR: out of the prescaler range: SrcSize/DstSize = %d(< 64)\n",SrcSize/DstSize);
		while(1);
	}
	else if(SrcSize>=32*DstSize)
	{
		*ratio=32;
		*shift=5;
	}
	else if(SrcSize>=16*DstSize) 
	{
		*ratio=16;
		*shift=4;
	}
	else if(SrcSize>=8*DstSize) 
	{
		*ratio=8;
		*shift=3;
	}
	else if(SrcSize>=4*DstSize) 
	{
		*ratio=4;
		*shift=2;
	}
	else if(SrcSize>=2*DstSize) 
	{
		*ratio=2;
		*shift=1;
	}
	else 
	{
		*ratio=1;
		*shift=0;
	}    
	
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//Description of Parameters
//CoDstWidth: Destination Width of Codec Path
//CoDstHeight: Destination Height of Codec Path
//PrDstWidth: Destination Width of Preview Path
//PrDstHeight: Destination Height of Preview Path
//WinHorOffset: Size of Window Offset for Horizontal Direction
//WinVerOffset: Size of Window Offset for Vertical Direction
//CoFrameBuffer: Start Address for Codec DMA
//PrFrameBuffer: Start Address for Previe DMA
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CamInit(uint CoDstWidth, uint CoDstHeight, uint PrDstWidth, uint PrDstHeight, uint WinHorOffset, uint WinVerOffset,  uint CoFrameBuffer, uint PrFrameBuffer)
{
	uint WinOfsEn;
	uint divisor, multiplier;
	uint MainBurstSizeY, RemainedBurstSizeY, MainBurstSizeC, RemainedBurstSizeC, MainBurstSizeRGB, RemainedBurstSizeRGB;
	uint H_Shift, V_Shift, PreHorRatio, PreVerRatio, MainHorRatio, MainVerRatio;
	uint SrcWidth, SrcHeight;
	uint ScaleUp_H_Co, ScaleUp_V_Co, ScaleUp_H_Pr, ScaleUp_V_Pr;

	//constant for calculating codec dma address
	if(CAM_CODEC_OUTPUT)
		divisor=2; //CCIR-422
	else
		divisor=4; //CCIR-420
		
	//constant for calculating preview dma address
	if(CAM_PVIEW_OUTPUT)
		multiplier=4;
	else
		multiplier=2;
	
	if(WinHorOffset==0 && WinVerOffset==0)
		WinOfsEn=0;
	else
		WinOfsEn=1;

	SrcWidth=CAM_SRC_HSIZE-WinHorOffset*2;
	SrcHeight=CAM_SRC_VSIZE-WinVerOffset*2;

	if(SrcWidth>=CoDstWidth) ScaleUp_H_Co=0; //down
	else ScaleUp_H_Co=1;		//up

	if(SrcHeight>=CoDstHeight) ScaleUp_V_Co=0;
	else ScaleUp_V_Co=1;		

	if(SrcWidth>=PrDstWidth) ScaleUp_H_Pr=0; //down
	else ScaleUp_H_Pr=1;		//up

	if(SrcHeight>=PrDstHeight) ScaleUp_V_Pr=0;   // edited 040225
	else ScaleUp_V_Pr=1;		

	////////////////// common control setting
	rCIGCTRL |= (1<<26)|(0<<27); // inverse PCLK, test pattern
	//--- capbily
	//rCIGCTRL |= (0<<26)|(0<<27); // don't inverse PCLK, test pattern
	//---
	rCIWDOFST = (1<<30)|(0xf<<12); // clear overflow 
	rCIWDOFST = 0;	
	rCIWDOFST=(WinOfsEn<<31)|(WinHorOffset<<16)|(WinVerOffset);
	rCISRCFMT=(((uint)CAM_ITU601)<<31)|(0<<30)|(0<<29)|(CAM_SRC_HSIZE<<16)|(CAM_ORDER_YCBYCR<<14)|(CAM_SRC_VSIZE);
	//--- capbily
	//rCISRCFMT=(CAM_ITU601<<31)|(1<<30)|(0<<29)|(CAM_SRC_HSIZE<<16)|(CAM_ORDER_YCBYCR<<14)|(CAM_SRC_VSIZE);
	//---

	////////////////// codec port setting
	if (CAM_CODEC_4PP)
	{
		rCICOYSA1=CoFrameBuffer;
		rCICOYSA2=rCICOYSA1+CoDstWidth*CoDstHeight+2*CoDstWidth*CoDstHeight/divisor;
		rCICOYSA3=rCICOYSA2+CoDstWidth*CoDstHeight+2*CoDstWidth*CoDstHeight/divisor;
		rCICOYSA4=rCICOYSA3+CoDstWidth*CoDstHeight+2*CoDstWidth*CoDstHeight/divisor;
		
		rCICOCBSA1=rCICOYSA1+CoDstWidth*CoDstHeight;
		rCICOCBSA2=rCICOYSA2+CoDstWidth*CoDstHeight;
		rCICOCBSA3=rCICOYSA3+CoDstWidth*CoDstHeight;
		rCICOCBSA4=rCICOYSA4+CoDstWidth*CoDstHeight;

		rCICOCRSA1=rCICOCBSA1+CoDstWidth*CoDstHeight/divisor;
		rCICOCRSA2=rCICOCBSA2+CoDstWidth*CoDstHeight/divisor;
		rCICOCRSA3=rCICOCBSA3+CoDstWidth*CoDstHeight/divisor;
		rCICOCRSA4=rCICOCBSA4+CoDstWidth*CoDstHeight/divisor;
	}
	else
	{
		rCICOYSA1=CoFrameBuffer;
		rCICOYSA2=rCICOYSA1;
		rCICOYSA3=rCICOYSA1;
		rCICOYSA4=rCICOYSA1;
		
		rCICOCBSA1=rCICOYSA1+CoDstWidth*CoDstHeight;
		rCICOCBSA2=rCICOCBSA1;
		rCICOCBSA3=rCICOCBSA1;
		rCICOCBSA4=rCICOCBSA1;
		
		rCICOCRSA1=rCICOCBSA1+CoDstWidth*CoDstHeight/divisor;
		rCICOCRSA2=rCICOCRSA1;
		rCICOCRSA3=rCICOCRSA1;
		rCICOCRSA4=rCICOCRSA1;
	}
	rCICOTRGFMT=(((uint)CAM_CODEC_IN_422)<<31)|(CAM_CODEC_OUTPUT<<30)|(CoDstWidth<<16)|(CAM_FLIP_180<<14)|(CoDstHeight);

	CalculateBurstSize(CoDstWidth, &MainBurstSizeY, &RemainedBurstSizeY);
	CalculateBurstSize(CoDstWidth/2, &MainBurstSizeC, &RemainedBurstSizeC);
	rCICOCTRL=(MainBurstSizeY<<19)|(RemainedBurstSizeY<<14)|(MainBurstSizeC<<9)|(RemainedBurstSizeC<<4);

	CalculatePrescalerRatioShift(SrcWidth, CoDstWidth, &PreHorRatio, &H_Shift);
	CalculatePrescalerRatioShift(SrcHeight, CoDstHeight, &PreVerRatio, &V_Shift);
	MainHorRatio=(SrcWidth<<8)/(CoDstWidth<<H_Shift);
	MainVerRatio=(SrcHeight<<8)/(CoDstHeight<<V_Shift);
    			
	rCICOSCPRERATIO=((10-H_Shift-V_Shift)<<28)|(PreHorRatio<<16)|(PreVerRatio);
	rCICOSCPREDST=((SrcWidth/PreHorRatio)<<16)|(SrcHeight/PreVerRatio); 
	rCICOSCCTRL=(CAM_SCALER_BYPASS_OFF<<31)|(ScaleUp_H_Co<<30)|(ScaleUp_V_Co<<29)|(MainHorRatio<<16)|(MainVerRatio);

	rCICOTAREA=CoDstWidth*CoDstHeight;

	///////////////// preview port setting
	if (CAM_PVIEW_4PP) // codec view mode
	{
		rCIPRCLRSA1=PrFrameBuffer;
		rCIPRCLRSA2=rCIPRCLRSA1+PrDstWidth*PrDstHeight*multiplier;
		rCIPRCLRSA3=rCIPRCLRSA2+PrDstWidth*PrDstHeight*multiplier;
		rCIPRCLRSA4=rCIPRCLRSA3+PrDstWidth*PrDstHeight*multiplier;
	}	
	else // direct preview mode
	{
		rCIPRCLRSA1 = (uint)LCD_BUFER;//LCD_BUFFER_CAM;
		rCIPRCLRSA2 = (uint)LCD_BUFER;//LCD_BUFFER_CAM;
		rCIPRCLRSA3 = (uint)LCD_BUFER;//LCD_BUFFER_CAM;
		rCIPRCLRSA4 = (uint)LCD_BUFER;//LCD_BUFFER_CAM;
	}	

	rCIPRTRGFMT=(PrDstWidth<<16)|(CAM_FLIP_180<<14)|(PrDstHeight);

	if (CAM_PVIEW_OUTPUT==CAM_RGB24B)
		CalculateBurstSize(PrDstWidth*2, &MainBurstSizeRGB, &RemainedBurstSizeRGB);
	else // RGB16B
		CalculateBurstSize(PrDstWidth*2, &MainBurstSizeRGB, &RemainedBurstSizeRGB);
   	rCIPRCTRL=(MainBurstSizeRGB<<19)|(RemainedBurstSizeRGB<<14);

	CalculatePrescalerRatioShift(SrcWidth, PrDstWidth, &PreHorRatio, &H_Shift);
	CalculatePrescalerRatioShift(SrcHeight, PrDstHeight, &PreVerRatio, &V_Shift);
	MainHorRatio=(SrcWidth<<8)/(PrDstWidth<<H_Shift);
	MainVerRatio=(SrcHeight<<8)/(PrDstHeight<<V_Shift);
	rCIPRSCPRERATIO=((10-H_Shift-V_Shift)<<28)|(PreHorRatio<<16)|(PreVerRatio);		 
	rCIPRSCPREDST=((SrcWidth/PreHorRatio)<<16)|(SrcHeight/PreVerRatio);
	rCIPRSCCTRL=(((uint)1)<<31)|(CAM_PVIEW_OUTPUT<<30)|(ScaleUp_H_Pr<<29)|(ScaleUp_V_Pr<<28)|(MainHorRatio<<16)|(MainVerRatio);
    
	rCIPRTAREA= PrDstWidth*PrDstHeight;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Test_CamPreview(void)
{

	
	DbgOut("\nNow Start Camera Preview\n");

	//camera global variables
	camTestMode=CAM_TEST_MODE_PVIEW|CAM_TEST_MODE_CODEC;
	camCodecCaptureCount=0;
	camPviewCaptureCount=0;
	camOutputCount=0;
	camPviewStatus=CAM_STOPPED;
	camCodecStatus=CAM_STOPPED;
	camOutputReady=0;

	Delay(300);

	CamInit(LCD_CAM_INPUT_XSIZE, LCD_CAM_INPUT_YSIZE, LCD_CAM_XSIZE, LCD_CAM_YSIZE, 0, 0,  (uint)CAM_FRAMEBUFFER_C, (uint)CAM_FRAMEBUFFER_P);

	Delay(300);

	// Start Capture	
	rSUBSRCPND|=BIT_SUB_CAM_C|BIT_SUB_CAM_P;
	ClearPending(BIT_CAM);
	pISR_CAM = (uint)CamIsr;
	
	CamPreviewIntUnmask();
	CamCodecIntUnmask();
	CamCaptureStart(CAM_PVIEW_SCALER_CAPTURE_ENABLE_BIT|CAM_CODEC_SCALER_CAPTURE_ENABLE_BIT);

	while(!camOutputReady);
	
	DbgOut("Preview Started!Press 'ESC' key to exit!\n");

#if 0
	while (1)
	{
		do{
		uartcmd=Uart_GetKey();
		}while((uartcmd!=0x13)&&(uartcmd!=ESC_KEY));

		if(uartcmd==ESC_KEY )
		break;
#if 1
		if(uartcmd==0x13 )		
		{
			if(camOutputReady)
			{
				bufidx=(((rCICOSTATUS>>26)&0x3)+4-2)%4;//current frame memory block
				switch(bufidx)
				{
					case 0:
						pOutBuf=(byte*)rCICOYSA1;
						break;
					case 1:
						pOutBuf=(byte*)rCICOYSA2;
						break;
					case 2:
						pOutBuf=(byte*)rCICOYSA3;
						break;
					case 3:
						pOutBuf=(byte*)rCICOYSA4;
						break;
				}
				for(i=0;i<LCD_CAM_XSIZE*LCD_CAM_YSIZE;i++)
				ImgOutBuf[i]=pOutBuf[i];
				UartPollBufOut(ImgOutBuf,LCD_CAM_XSIZE*LCD_CAM_YSIZE);

				camOutputReady=0;
			}
		}
#endif		
	}
    
	CamCaptureStop();
	while(camPviewStatus!=CAM_STOPPED)
	if (Uart_GetKey()== '\r') break;	
#endif
	DbgOut("camCodecCaptureCount=%d\n",camCodecCaptureCount);
	DbgOut("camPviewCaptureCount=%d\n",camPviewCaptureCount);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void SetupOV9620(void)
{
	int i,addlen;
	byte regval[2],regvalb[2];

	SetupI2COV9620();

	//while(1)
	{
		I2CReadOV9620(OV9620_SCCB_ID,0x1c,&regval[0],2);
		Delay(500);

		DbgOut("I2C to OV7620!%x:%x\n",regval[0],regval[1]);

		I2CReadOV9620(OV9620_SCCB_ID,0x1c,&regval[0],2);
		if((regval[0]!=((OV7620_PRODUCT_ID>>8)&0xff))||(regval[1]!=(OV7620_PRODUCT_ID&0xff)))
		DbgOut("M ID is 0x%x%x!\n",regval[0],regval[1]);

		regval[0]=0x80;
		I2CWriteOV9620(OV9620_SCCB_ID,0x12,&regval[0],1);	
		Delay(500);
	}
	addlen=sizeof(ov9650_reg)/sizeof(OVVisionREG);

	for (i=0;i<addlen;) 
	{
		I2CReadOV9620(OV9620_SCCB_ID,ov9650_reg[i].subaddr,&regvalb[0],1);
		I2CWriteOV9620(OV9620_SCCB_ID,ov9650_reg[i].subaddr,&ov9650_reg[i].value,1);
		I2CReadOV9620(OV9620_SCCB_ID,ov9650_reg[i].subaddr,&regval[0],1);

		DbgOut("		Addr=[0x%x] Before=(0x%x) Write=(0x%x)  After=(0x%x) \n",ov9650_reg[i].subaddr,regvalb[0],ov9650_reg[i].value,regval[0]);
		if(regval[0]!=ov9650_reg[i].value)
		DbgOut("Error !!!!  Addr=[0x%x] valw=(0x%x) valr=(0x%x)\n",ov9650_reg[i].subaddr,ov9650_reg[i].value,regval[0]);
//		else
		i++;

	}
#if 1
	for (i=0;i<addlen;i++) 
	{
		I2CReadOV9620(OV9620_SCCB_ID,ov9650_reg[i].subaddr,&regvalb[0],1);
		I2CWriteOV9620(OV9620_SCCB_ID,ov9650_reg[i].subaddr,&ov9650_reg[i].value,1);
		I2CReadOV9620(OV9620_SCCB_ID,ov9650_reg[i].subaddr,&regval[0],1);
		if(regval[0]!=ov9650_reg[i].value)
		DbgOut("Error !!!!  Addr=[0x%x] valw=(0x%x) valr=(0x%x)\n",ov9650_reg[i].subaddr,ov9650_reg[i].value,regval[0]);
	}
#endif	

}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 0:48MHz, 1:24MHz, 2:16MHz, 3:12MHz...
// Camera clock = UPLL/[(CAMCLK_DIV+1)X2]
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void SetCAMClockDivider(int divn) 
{
	rCAMDIVN = (rCAMDIVN & ~(0xf))|(1<<4)|(divn); // CAMCLK is divided..
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CamSetup(void)
{
	rCIGCTRL|=(((uint)1)<<31); //camera I/F soft reset
	Delay(100);
	rCIGCTRL&=(~(((uint)1)<<31));
	Delay(100);

	// Initializing camif
	rCLKCON |= (1<<19); // enable camclk
	
	rGPJCON=0x2aaaaaa;
	rGPJDAT=0;
	rGPJUP=0;

#if 0	
	//--- capbily
	rGPGCON&=~(3<<24);
	rGPGCON|=1<<24;
	rGPGUP|=1<<12;
	rGPGDAT&=~(1<<12);
#endif

	rCLKDIVN|=(1<<3); // UCLK 48MHz setting for UPLL 96MHz
	// 0:48MHz, 1:24MHz, 2:16MHz, 3:12MHz...
	// Camera clock = UPLL/[(CAMCLK_DIV+1)X2]
	//SetCAMClockDivider(CAMCLK24000000); //Set Camera Clock 24MHz s5x532, ov7620
	SetCAMClockDivider(CAMCLK24000000); //Set Camera Clock 24MHz s5x532, ov7620
	//SetCAMClockDivider(CAMCLK9600000); //Set Camera Clock 24MHz s5x532, ov7620

	SetupOV9620();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CameraTest(void)
{
	DbgOut("Initial Camera now, Please wait for a while!\n");
	
	CamSetup();

	Test_CamPreview() ;

	DbgOut("\nCamera Preview Test End\n");
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void OutputCamBuf(void)
{
	uint bufidx;
	byte *pOutBuf;
	uint idx0;
	
	bufidx=(((rCIPRSTATUS>>26)&0x3)+4-2)%4;//current frame memory block
	switch(bufidx)
	{
		case 0:
			pOutBuf=(byte*)rCIPRCLRSA1;
			break;
		case 1:
			pOutBuf=(byte*)rCIPRCLRSA2;
			break;
		case 2:
			pOutBuf=(byte*)rCIPRCLRSA3;
			break;
		case 3:
			pOutBuf=(byte*)rCIPRCLRSA4;
			break;
		default:
			break;
	}
	for(idx0=0;idx0<LCD_CAM_XSIZE*LCD_CAM_YSIZE*2;idx0++)
	CamProcBuf[idx0]=pOutBuf[idx0];

	LCDCamBufDrawBMP(0,0,LCD_CAM_XSIZE,LCD_CAM_YSIZE,CamProcBuf,LCD_CAM_XSIZE,LCD_CAM_YSIZE);
	//LCDBufDrawBMP(0,0,240,180,LCDDISPBMP_caomai,LCD_SIZE_X,LCD_SIZE_Y);
	
	
}
